/*
 * Copyright (C) 2019 xuexiangjys(xuexiangjys@163.com)
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */
package com.gmlive.common.ui.xui.helper

import android.annotation.TargetApi
import android.content.Context
import android.graphics.*
import android.os.Build
import android.util.AttributeSet
import android.view.View
import android.view.ViewOutlineProvider
import androidx.annotation.ColorInt
import com.gmlive.common.ui.R
import com.gmlive.common.ui.xui.IXUILayout
import com.gmlive.common.ui.xui.IXUILayout.HideRadiusSide
import com.gmlive.common.ui.xui.ThemeUtils
import com.gmlive.common.ui.xui.ThemeUtils.resolveDimension
import java.lang.ref.WeakReference
import kotlin.math.floor

/**
 * 布局辅助工具
 *
 * @author xuexiang
 * @since 2019-06-01 19:30
 */
class XUILayoutHelper(private val mContext: Context, attrs: AttributeSet?, defAttr: Int, owner: View) : IXUILayout {

    // size
    private var mWidthLimit = 0
    private var mHeightLimit = 0
    private var mWidthMini = 0
    private var mHeightMini = 0

    // divider
    private var mTopDividerHeight = 0
    private var mTopDividerInsetLeft = 0
    private var mTopDividerInsetRight = 0
    private var mTopDividerColor: Int
    private var mTopDividerAlpha = 255
    private var mBottomDividerHeight = 0
    private var mBottomDividerInsetLeft = 0
    private var mBottomDividerInsetRight = 0
    private var mBottomDividerColor: Int
    private var mBottomDividerAlpha = 255
    private var mLeftDividerWidth = 0
    private var mLeftDividerInsetTop = 0
    private var mLeftDividerInsetBottom = 0
    private var mLeftDividerColor = 0
    private var mLeftDividerAlpha = 255
    private var mRightDividerWidth = 0
    private var mRightDividerInsetTop = 0
    private var mRightDividerInsetBottom = 0
    private var mRightDividerColor = 0
    private var mRightDividerAlpha = 255
    private var mDividerPaint: Paint? = null

    // round
    private val mClipPaint: Paint
    private val mMode: PorterDuffXfermode
    private var mRadius = 0

    @HideRadiusSide
    private var mHideRadiusSide: Int = IXUILayout.HIDE_RADIUS_SIDE_NONE
    private var mRadiusArray: FloatArray? = null
    private val mBorderRect: RectF
    private var mBorderColor = 0
    private var mBorderWidth = 1
    private var mOuterNormalColor = 0
    private val mOwner: WeakReference<View>
    private var mIsOutlineExcludePadding = false
    private val mPath = Path()

    // shadow
    private var mIsShowBorderOnlyBeforeL = true
    private var mShadowElevation = 0
    private var mShadowAlpha: Float
    private var mShadowColor = Color.BLACK

    // outline inset
    private var mOutlineInsetLeft = 0
    private var mOutlineInsetRight = 0
    private var mOutlineInsetTop = 0
    private var mOutlineInsetBottom = 0
    override fun setUseThemeGeneralShadowElevation() {
        mShadowElevation = resolveDimension(mContext, R.attr.xui_general_shadow_elevation)
        setRadiusAndShadow(mRadius, mHideRadiusSide, mShadowElevation, mShadowAlpha)
    }

    override fun setOutlineExcludePadding(outlineExcludePadding: Boolean) {
        if (useFeature()) {
            val owner = mOwner.get() ?: return
            mIsOutlineExcludePadding = outlineExcludePadding
            owner.invalidateOutline()
        }
    }

    override fun setWidthLimit(widthLimit: Int): Boolean {
        if (mWidthLimit != widthLimit) {
            mWidthLimit = widthLimit
            return true
        }
        return false
    }

    override fun setHeightLimit(heightLimit: Int): Boolean {
        if (mHeightLimit != heightLimit) {
            mHeightLimit = heightLimit
            return true
        }
        return false
    }

    override var shadowElevation: Int
        get() = mShadowElevation
        set(elevation) {
            if (mShadowElevation == elevation) {
                return
            }
            mShadowElevation = elevation
            invalidate()
        }

    override var shadowAlpha: Float
        get() = mShadowAlpha
        set(shadowAlpha) {
            if (mShadowAlpha == shadowAlpha) {
                return
            }
            mShadowAlpha = shadowAlpha
            invalidate()
        }

    override var _shadowColor: Int
        get() = mShadowColor
        set(shadowColor) {
            if (mShadowColor == shadowColor) {
                return
            }
            mShadowColor = shadowColor
            setShadowColorInner(mShadowColor)
        }

    override fun setOutlineInset(left: Int, top: Int, right: Int, bottom: Int) {
        if (useFeature()) {
            val owner = mOwner.get() ?: return
            mOutlineInsetLeft = left
            mOutlineInsetRight = right
            mOutlineInsetTop = top
            mOutlineInsetBottom = bottom
            owner.invalidateOutline()
        }
    }

    override fun setShowBorderOnlyBeforeL(showBorderOnlyBeforeL: Boolean) {
        mIsShowBorderOnlyBeforeL = showBorderOnlyBeforeL
        invalidate()
    }

    private fun setShadowColorInner(shadowColor: Int) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
            val owner = mOwner.get() ?: return
            owner.outlineAmbientShadowColor = shadowColor
            owner.outlineSpotShadowColor = shadowColor
        }
    }

    private fun invalidate() {
        if (useFeature()) {
            val owner = mOwner.get() ?: return
            if (mShadowElevation == 0) {
                owner.elevation = 0f
            } else {
                owner.elevation = mShadowElevation.toFloat()
            }
            owner.invalidateOutline()
        }
    }

    override var hideRadiusSide: Int
        get() = mHideRadiusSide
        set(hideRadiusSide) {
            if (mHideRadiusSide == hideRadiusSide) {
                return
            }
            setRadiusAndShadow(mRadius, hideRadiusSide, mShadowElevation, mShadowAlpha)
        }

    override fun setRadius(radius: Int, @HideRadiusSide hideRadiusSide: Int) {
        if (mRadius == radius && hideRadiusSide == mHideRadiusSide) {
            return
        }
        setRadiusAndShadow(radius, hideRadiusSide, mShadowElevation, mShadowAlpha)
    }

    override var radius: Int
        get() = mRadius
        set(radius) {
            if (mRadius != radius) {
                setRadiusAndShadow(radius, mShadowElevation, mShadowAlpha)
            }
        }

    override fun setRadiusAndShadow(radius: Int, shadowElevation: Int, shadowAlpha: Float) {
        setRadiusAndShadow(radius, mHideRadiusSide, shadowElevation, shadowAlpha)
    }

    override fun setRadiusAndShadow(radius: Int, @HideRadiusSide hideRadiusSide: Int, shadowElevation: Int, shadowAlpha: Float) {
        setRadiusAndShadow(radius, hideRadiusSide, shadowElevation, mShadowColor, shadowAlpha)
    }

    override fun setRadiusAndShadow(radius: Int, hideRadiusSide: Int, shadowElevation: Int, shadowColor: Int, shadowAlpha: Float) {
        val owner = mOwner.get() ?: return
        mRadius = radius
        mHideRadiusSide = hideRadiusSide
        if (mRadius > 0) {
            mRadiusArray = if (hideRadiusSide == IXUILayout.HIDE_RADIUS_SIDE_TOP) {
                floatArrayOf(0f, 0f, 0f, 0f, mRadius.toFloat(), mRadius.toFloat(), mRadius.toFloat(), mRadius.toFloat())
            } else if (hideRadiusSide == IXUILayout.HIDE_RADIUS_SIDE_RIGHT) {
                floatArrayOf(mRadius.toFloat(), mRadius.toFloat(), 0f, 0f, 0f, 0f, mRadius.toFloat(), mRadius.toFloat())
            } else if (hideRadiusSide == IXUILayout.HIDE_RADIUS_SIDE_BOTTOM) {
                floatArrayOf(mRadius.toFloat(), mRadius.toFloat(), mRadius.toFloat(), mRadius.toFloat(), 0f, 0f, 0f, 0f)
            } else if (hideRadiusSide == IXUILayout.HIDE_RADIUS_SIDE_LEFT) {
                floatArrayOf(0f, 0f, mRadius.toFloat(), mRadius.toFloat(), mRadius.toFloat(), mRadius.toFloat(), 0f, 0f)
            } else {
                null
            }
        }
        mShadowElevation = shadowElevation
        mShadowAlpha = shadowAlpha
        mShadowColor = shadowColor
        if (useFeature()) {
            if (mShadowElevation == 0 || isRadiusWithSideHidden) {
                owner.elevation = 0f
            } else {
                owner.elevation = mShadowElevation.toFloat()
            }
            setShadowColorInner(mShadowColor)
            owner.outlineProvider = object : ViewOutlineProvider() {
                @TargetApi(21)
                override fun getOutline(view: View, outline: Outline) {
                    val w = view.width
                    val h = view.height
                    if (w == 0 || h == 0) {
                        return
                    }
                    mRadius = mRadius.coerceAtMost(h.div(2)).coerceAtMost(w.div(2))
                    if (isRadiusWithSideHidden) {
                        var left = 0
                        var top = 0
                        var right = w
                        var bottom = h
                        if (mHideRadiusSide == IXUILayout.HIDE_RADIUS_SIDE_LEFT) {
                            left -= mRadius
                        } else if (mHideRadiusSide == IXUILayout.HIDE_RADIUS_SIDE_TOP) {
                            top -= mRadius
                        } else if (mHideRadiusSide == IXUILayout.HIDE_RADIUS_SIDE_RIGHT) {
                            right += mRadius
                        } else if (mHideRadiusSide == IXUILayout.HIDE_RADIUS_SIDE_BOTTOM) {
                            bottom += mRadius
                        }
                        outline.setRoundRect(left, top,
                                right, bottom, mRadius.toFloat())
                        return
                    }
                    var top = mOutlineInsetTop
                    var bottom = Math.max(top + 1, h - mOutlineInsetBottom)
                    var left = mOutlineInsetLeft
                    var right = w - mOutlineInsetRight
                    if (mIsOutlineExcludePadding) {
                        left += view.paddingLeft
                        top += view.paddingTop
                        right = Math.max(left + 1, right - view.paddingRight)
                        bottom = Math.max(top + 1, bottom - view.paddingBottom)
                    }
                    var shadowAlpha = mShadowAlpha
                    if (mShadowElevation == 0) {
                        // outline.setAlpha will work even if shadowElevation == 0
                        shadowAlpha = 1f
                    }
                    outline.alpha = shadowAlpha
                    if (mRadius <= 0) {
                        outline.setRect(left, top,
                                right, bottom)
                    } else {
                        outline.setRoundRect(left, top,
                                right, bottom, mRadius.toFloat())
                    }
                }
            }
            owner.clipToOutline = mRadius > 0
        }
        owner.invalidate()
    }

    /**
     * 有radius, 但是有一边不显示radius。
     *
     * @return
     */
    val isRadiusWithSideHidden: Boolean
        get() = mRadius > 0 && mHideRadiusSide != IXUILayout.HIDE_RADIUS_SIDE_NONE

    override fun updateTopDivider(topInsetLeft: Int, topInsetRight: Int, topDividerHeight: Int, topDividerColor: Int) {
        mTopDividerInsetLeft = topInsetLeft
        mTopDividerInsetRight = topInsetRight
        mTopDividerHeight = topDividerHeight
        mTopDividerColor = topDividerColor
    }

    override fun updateBottomDivider(bottomInsetLeft: Int, bottomInsetRight: Int, bottomDividerHeight: Int, bottomDividerColor: Int) {
        mBottomDividerInsetLeft = bottomInsetLeft
        mBottomDividerInsetRight = bottomInsetRight
        mBottomDividerColor = bottomDividerColor
        mBottomDividerHeight = bottomDividerHeight
    }

    override fun updateLeftDivider(leftInsetTop: Int, leftInsetBottom: Int, leftDividerWidth: Int, leftDividerColor: Int) {
        mLeftDividerInsetTop = leftInsetTop
        mLeftDividerInsetBottom = leftInsetBottom
        mLeftDividerWidth = leftDividerWidth
        mLeftDividerColor = leftDividerColor
    }

    override fun updateRightDivider(rightInsetTop: Int, rightInsetBottom: Int, rightDividerWidth: Int, rightDividerColor: Int) {
        mRightDividerInsetTop = rightInsetTop
        mRightDividerInsetBottom = rightInsetBottom
        mRightDividerWidth = rightDividerWidth
        mRightDividerColor = rightDividerColor
    }

    override fun onlyShowTopDivider(topInsetLeft: Int, topInsetRight: Int,
                                    topDividerHeight: Int, topDividerColor: Int) {
        updateTopDivider(topInsetLeft, topInsetRight, topDividerHeight, topDividerColor)
        mLeftDividerWidth = 0
        mRightDividerWidth = 0
        mBottomDividerHeight = 0
    }

    override fun onlyShowBottomDivider(bottomInsetLeft: Int, bottomInsetRight: Int,
                                       bottomDividerHeight: Int, bottomDividerColor: Int) {
        updateBottomDivider(bottomInsetLeft, bottomInsetRight, bottomDividerHeight, bottomDividerColor)
        mLeftDividerWidth = 0
        mRightDividerWidth = 0
        mTopDividerHeight = 0
    }

    override fun onlyShowLeftDivider(leftInsetTop: Int, leftInsetBottom: Int, leftDividerWidth: Int, leftDividerColor: Int) {
        updateLeftDivider(leftInsetTop, leftInsetBottom, leftDividerWidth, leftDividerColor)
        mRightDividerWidth = 0
        mTopDividerHeight = 0
        mBottomDividerHeight = 0
    }

    override fun onlyShowRightDivider(rightInsetTop: Int, rightInsetBottom: Int, rightDividerWidth: Int, rightDividerColor: Int) {
        updateRightDivider(rightInsetTop, rightInsetBottom, rightDividerWidth, rightDividerColor)
        mLeftDividerWidth = 0
        mTopDividerHeight = 0
        mBottomDividerHeight = 0
    }

    override fun setTopDividerAlpha(dividerAlpha: Int) {
        mTopDividerAlpha = dividerAlpha
    }

    override fun setBottomDividerAlpha(dividerAlpha: Int) {
        mBottomDividerAlpha = dividerAlpha
    }

    override fun setLeftDividerAlpha(dividerAlpha: Int) {
        mLeftDividerAlpha = dividerAlpha
    }

    override fun setRightDividerAlpha(dividerAlpha: Int) {
        mRightDividerAlpha = dividerAlpha
    }

    fun handleMiniWidth(widthMeasureSpec: Int, measuredWidth: Int): Int {
        return if (View.MeasureSpec.getMode(widthMeasureSpec) != View.MeasureSpec.EXACTLY
                && measuredWidth < mWidthMini) {
            View.MeasureSpec.makeMeasureSpec(mWidthMini, View.MeasureSpec.EXACTLY)
        } else widthMeasureSpec
    }

    fun handleMiniHeight(heightMeasureSpec: Int, measuredHeight: Int): Int {
        return if (View.MeasureSpec.getMode(heightMeasureSpec) != View.MeasureSpec.EXACTLY
                && measuredHeight < mHeightMini) {
            View.MeasureSpec.makeMeasureSpec(mHeightMini, View.MeasureSpec.EXACTLY)
        } else heightMeasureSpec
    }

    fun getMeasuredWidthSpec(widthMeasureSpec: Int): Int {
        var widthMeasureSpec = widthMeasureSpec
        if (mWidthLimit > 0) {
            val size = View.MeasureSpec.getSize(widthMeasureSpec)
            if (size > mWidthLimit) {
                val mode = View.MeasureSpec.getMode(widthMeasureSpec)
                widthMeasureSpec = if (mode == View.MeasureSpec.AT_MOST) {
                    View.MeasureSpec.makeMeasureSpec(mWidthLimit, View.MeasureSpec.AT_MOST)
                } else {
                    View.MeasureSpec.makeMeasureSpec(mWidthLimit, View.MeasureSpec.EXACTLY)
                }
            }
        }
        return widthMeasureSpec
    }

    fun getMeasuredHeightSpec(heightMeasureSpec: Int): Int {
        var heightMeasureSpec = heightMeasureSpec
        if (mHeightLimit > 0) {
            val size = View.MeasureSpec.getSize(heightMeasureSpec)
            if (size > mHeightLimit) {
                val mode = View.MeasureSpec.getMode(heightMeasureSpec)
                heightMeasureSpec = if (mode == View.MeasureSpec.AT_MOST) {
                    View.MeasureSpec.makeMeasureSpec(mWidthLimit, View.MeasureSpec.AT_MOST)
                } else {
                    View.MeasureSpec.makeMeasureSpec(mWidthLimit, View.MeasureSpec.EXACTLY)
                }
            }
        }
        return heightMeasureSpec
    }

    override fun setBorderColor(@ColorInt borderColor: Int) {
        mBorderColor = borderColor
    }

    override fun setBorderWidth(borderWidth: Int) {
        mBorderWidth = borderWidth
    }

    override fun setOuterNormalColor(color: Int) {
        mOuterNormalColor = color
        val owner = mOwner.get()
        owner?.invalidate()
    }

    fun drawDividers(canvas: Canvas, w: Int, h: Int) {
        if (mDividerPaint == null &&
                (mTopDividerHeight > 0 || mBottomDividerHeight > 0 || mLeftDividerWidth > 0 || mRightDividerWidth > 0)) {
            mDividerPaint = Paint()
        }
        if (mTopDividerHeight > 0) {
            mDividerPaint?.strokeWidth = mTopDividerHeight.toFloat()
            mDividerPaint?.color = mTopDividerColor
            if (mTopDividerAlpha < 255) {
                mDividerPaint?.alpha = mTopDividerAlpha
            }
            val y = mTopDividerHeight * 1f / 2
            mDividerPaint?.let { canvas.drawLine(mTopDividerInsetLeft.toFloat(), y, w - mTopDividerInsetRight.toFloat(), y, it) }
        }
        if (mBottomDividerHeight > 0) {
            mDividerPaint?.strokeWidth = mBottomDividerHeight.toFloat()
            mDividerPaint?.color = mBottomDividerColor
            if (mBottomDividerAlpha < 255) {
                mDividerPaint?.alpha = mBottomDividerAlpha
            }
            val y = floor(h - mBottomDividerHeight * 1f / 2.toDouble()).toFloat()
            mDividerPaint?.let { canvas.drawLine(mBottomDividerInsetLeft.toFloat(), y, w - mBottomDividerInsetRight.toFloat(), y, it) }
        }
        if (mLeftDividerWidth > 0) {
            mDividerPaint?.strokeWidth = mLeftDividerWidth.toFloat()
            mDividerPaint?.color = mLeftDividerColor
            if (mLeftDividerAlpha < 255) {
                mDividerPaint?.alpha = mLeftDividerAlpha
            }
            mDividerPaint?.let { canvas.drawLine(0f, mLeftDividerInsetTop.toFloat(), 0f, h - mLeftDividerInsetBottom.toFloat(), it) }
        }
        if (mRightDividerWidth > 0) {
            mDividerPaint?.strokeWidth = mRightDividerWidth.toFloat()
            mDividerPaint?.color = mRightDividerColor
            if (mRightDividerAlpha < 255) {
                mDividerPaint?.alpha = mRightDividerAlpha
            }
            mDividerPaint?.let { canvas.drawLine(w.toFloat(), mRightDividerInsetTop.toFloat(), w.toFloat(), h - mRightDividerInsetBottom.toFloat(), it) }
        }
    }

    fun dispatchRoundBorderDraw(canvas: Canvas) {
        val owner = mOwner.get() ?: return
        if (mBorderColor == 0 && (mRadius == 0 || mOuterNormalColor == 0)) {
            return
        }
        if (mIsShowBorderOnlyBeforeL && useFeature() && mShadowElevation != 0) {
            return
        }
        val width = canvas.width
        val height = canvas.height

        // react
        if (mIsOutlineExcludePadding) {
            mBorderRect[1 + owner.paddingLeft.toFloat(), 1 + owner.paddingTop.toFloat(), width - 1 - owner.paddingRight.toFloat()] = height - 1 - owner.paddingBottom.toFloat()
        } else {
            mBorderRect[1f, 1f, width - 1.toFloat()] = height - 1.toFloat()
        }
        if (mRadius == 0 || !useFeature() && mOuterNormalColor == 0) {
            mClipPaint.style = Paint.Style.STROKE
            mClipPaint.color = mBorderColor
            canvas.drawRect(mBorderRect, mClipPaint)
            return
        }

        // 圆角矩形
        if (!useFeature()) {
            val layerId = canvas.saveLayer(0f, 0f, width.toFloat(), height.toFloat(), null, Canvas.ALL_SAVE_FLAG)
            canvas.drawColor(mOuterNormalColor)
            mClipPaint.color = mOuterNormalColor
            mClipPaint.style = Paint.Style.FILL
            mClipPaint.xfermode = mMode
            if (mRadiusArray == null) {
                canvas.drawRoundRect(mBorderRect, mRadius.toFloat(), mRadius.toFloat(), mClipPaint)
            } else {
                drawRoundRect(canvas, mBorderRect, mRadiusArray!!, mClipPaint)
            }
            mClipPaint.xfermode = null
            canvas.restoreToCount(layerId)
        }
        mClipPaint.color = mBorderColor
        mClipPaint.strokeWidth = mBorderWidth.toFloat()
        mClipPaint.style = Paint.Style.STROKE
        if (mRadiusArray == null) {
            canvas.drawRoundRect(mBorderRect, mRadius.toFloat(), mRadius.toFloat(), mClipPaint)
        } else {
            drawRoundRect(canvas, mBorderRect, mRadiusArray!!, mClipPaint)
        }
    }

    private fun drawRoundRect(canvas: Canvas, rect: RectF, radiusArray: FloatArray, paint: Paint) {
        mPath.reset()
        mPath.addRoundRect(rect, radiusArray, Path.Direction.CW)
        canvas.drawPath(mPath, paint)
    }

    companion object {
        fun useFeature(): Boolean {
            return Build.VERSION.SDK_INT >= 21
        }
    }

    init {
        mOwner = WeakReference(owner)
        mTopDividerColor = ThemeUtils.resolveColor(mContext, R.attr.xui_config_color_separator_light)
        mBottomDividerColor = mTopDividerColor
        mMode = PorterDuffXfermode(PorterDuff.Mode.DST_OUT)
        mClipPaint = Paint()
        mClipPaint.isAntiAlias = true
        mShadowAlpha = ThemeUtils.resolveFloat(mContext, R.attr.xui_general_shadow_alpha)
        mBorderRect = RectF()
        var radius = 0
        var shadow = 0
        var useThemeGeneralShadowElevation = false
        if (null != attrs || defAttr != 0) {
            val ta = mContext.obtainStyledAttributes(attrs, R.styleable.XUILayout, defAttr, 0)
            val count = ta.indexCount
            for (i in 0 until count) {
                when (val index = ta.getIndex(i)) {
                    R.styleable.XUILayout_android_maxWidth -> {
                        mWidthLimit = ta.getDimensionPixelSize(index, mWidthLimit)
                    }
                    R.styleable.XUILayout_android_maxHeight -> {
                        mHeightLimit = ta.getDimensionPixelSize(index, mHeightLimit)
                    }
                    R.styleable.XUILayout_android_minWidth -> {
                        mWidthMini = ta.getDimensionPixelSize(index, mWidthMini)
                    }
                    R.styleable.XUILayout_android_minHeight -> {
                        mHeightMini = ta.getDimensionPixelSize(index, mHeightMini)
                    }
                    R.styleable.XUILayout_xui_topDividerColor -> {
                        mTopDividerColor = ta.getColor(index, mTopDividerColor)
                    }
                    R.styleable.XUILayout_xui_topDividerHeight -> {
                        mTopDividerHeight = ta.getDimensionPixelSize(index, mTopDividerHeight)
                    }
                    R.styleable.XUILayout_xui_topDividerInsetLeft -> {
                        mTopDividerInsetLeft = ta.getDimensionPixelSize(index, mTopDividerInsetLeft)
                    }
                    R.styleable.XUILayout_xui_topDividerInsetRight -> {
                        mTopDividerInsetRight = ta.getDimensionPixelSize(index, mTopDividerInsetRight)
                    }
                    R.styleable.XUILayout_xui_bottomDividerColor -> {
                        mBottomDividerColor = ta.getColor(index, mBottomDividerColor)
                    }
                    R.styleable.XUILayout_xui_bottomDividerHeight -> {
                        mBottomDividerHeight = ta.getDimensionPixelSize(index, mBottomDividerHeight)
                    }
                    R.styleable.XUILayout_xui_bottomDividerInsetLeft -> {
                        mBottomDividerInsetLeft = ta.getDimensionPixelSize(index, mBottomDividerInsetLeft)
                    }
                    R.styleable.XUILayout_xui_bottomDividerInsetRight -> {
                        mBottomDividerInsetRight = ta.getDimensionPixelSize(index, mBottomDividerInsetRight)
                    }
                    R.styleable.XUILayout_xui_leftDividerColor -> {
                        mLeftDividerColor = ta.getColor(index, mLeftDividerColor)
                    }
                    R.styleable.XUILayout_xui_leftDividerWidth -> {
                        mLeftDividerWidth = ta.getDimensionPixelSize(index, mBottomDividerHeight)
                    }
                    R.styleable.XUILayout_xui_leftDividerInsetTop -> {
                        mLeftDividerInsetTop = ta.getDimensionPixelSize(index, mLeftDividerInsetTop)
                    }
                    R.styleable.XUILayout_xui_leftDividerInsetBottom -> {
                        mLeftDividerInsetBottom = ta.getDimensionPixelSize(index, mLeftDividerInsetBottom)
                    }
                    R.styleable.XUILayout_xui_rightDividerColor -> {
                        mRightDividerColor = ta.getColor(index, mRightDividerColor)
                    }
                    R.styleable.XUILayout_xui_rightDividerWidth -> {
                        mRightDividerWidth = ta.getDimensionPixelSize(index, mRightDividerWidth)
                    }
                    R.styleable.XUILayout_xui_rightDividerInsetTop -> {
                        mRightDividerInsetTop = ta.getDimensionPixelSize(index, mRightDividerInsetTop)
                    }
                    R.styleable.XUILayout_xui_rightDividerInsetBottom -> {
                        mRightDividerInsetBottom = ta.getDimensionPixelSize(index, mRightDividerInsetBottom)
                    }
                    R.styleable.XUILayout_xui_borderColor -> {
                        mBorderColor = ta.getColor(index, mBorderColor)
                    }
                    R.styleable.XUILayout_xui_borderWidth -> {
                        mBorderWidth = ta.getDimensionPixelSize(index, mBorderWidth)
                    }
                    R.styleable.XUILayout_xui_radius -> {
                        radius = ta.getDimensionPixelSize(index, 0)
                    }
                    R.styleable.XUILayout_xui_outerNormalColor -> {
                        mOuterNormalColor = ta.getColor(index, mOuterNormalColor)
                    }
                    R.styleable.XUILayout_xui_hideRadiusSide -> {
                        mHideRadiusSide = ta.getColor(index, mHideRadiusSide)
                    }
                    R.styleable.XUILayout_xui_showBorderOnlyBeforeL -> {
                        mIsShowBorderOnlyBeforeL = ta.getBoolean(index, mIsShowBorderOnlyBeforeL)
                    }
                    R.styleable.XUILayout_xui_shadowElevation -> {
                        shadow = ta.getDimensionPixelSize(index, shadow)
                    }
                    R.styleable.XUILayout_xui_shadowAlpha -> {
                        mShadowAlpha = ta.getFloat(index, mShadowAlpha)
                    }
                    R.styleable.XUILayout_xui_useThemeGeneralShadowElevation -> {
                        useThemeGeneralShadowElevation = ta.getBoolean(index, false)
                    }
                    R.styleable.XUILayout_xui_outlineInsetLeft -> {
                        mOutlineInsetLeft = ta.getDimensionPixelSize(index, 0)
                    }
                    R.styleable.XUILayout_xui_outlineInsetRight -> {
                        mOutlineInsetRight = ta.getDimensionPixelSize(index, 0)
                    }
                    R.styleable.XUILayout_xui_outlineInsetTop -> {
                        mOutlineInsetTop = ta.getDimensionPixelSize(index, 0)
                    }
                    R.styleable.XUILayout_xui_outlineInsetBottom -> {
                        mOutlineInsetBottom = ta.getDimensionPixelSize(index, 0)
                    }
                    R.styleable.XUILayout_xui_outlineExcludePadding -> {
                        mIsOutlineExcludePadding = ta.getBoolean(index, false)
                    }
                }
            }
            ta.recycle()
        }
        if (shadow == 0 && useThemeGeneralShadowElevation) {
            shadow = resolveDimension(mContext, R.attr.xui_general_shadow_elevation)
        }
        setRadiusAndShadow(radius, mHideRadiusSide, shadow, mShadowAlpha)
    }
}